# 列表生成式可以很简洁地表达循环
L = list(range(1, 11))
print([x * x for x in L])

# 要输出偶数的平方根，则需要在 for 循环后面加上条件



# experiment
L1 = ['Hello', 'World', 18, 'Apple', None]
L2 = [s.lower() for s in L1 if isinstance(s, str)]

# 测试:
print(L2)
if L2 == ['hello', 'world', 'apple']:
    print('测试通过!')
else:
    print('测试失败!')

# 生成器：一边循环，一边计算的机制
# 如果列表元素是按照某种算法生成的，那么可以不用创建列表，而是创建一个生成器，可以节省大量空间
g = (x * x for x in range(1, 11))
print(next(g))

# 如果某个函数也满足一定的算法规则，所以可以用 yield 关键字，将其变为 generator 函数
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print(b)
        a, b = b, a + b
        n = n + 1
    return 'done'

print(fib(6))

# generator 函数
def fib_generator(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'

f = fib_generator(6)
print(type(f))

for n in f:
    print(n)

# 调用generator函数会创建一个generator对象，多次调用generator函数会创建多个相互独立的generator。
def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield(3)
    print('step 3')
    yield(5)
o = odd()
print(next(o))
print(next(o))

print(next(odd()))

# 想要拿到 generator 函数的返回值，就需要捕获 StopIteration 错误，返回值包含在 StopIteration 的 value 中
g = fib_generator(10)
while True:
    try:
        x = next(g)
        print('g:', x)
    except StopIteration as e:
        print('Generator return value:', e.value)
        break

def triangles():
    k = 0
    L = [1]
    while True:
        yield L
        tmp = []
        for i, n in enumerate(L):
            if i == 0:
                tmp.append(1)
            else:
                tmp.append(L[i] + L[i - 1])
        tmp.append(1)
        L = tmp

# 期待输出:
# [1]
# [1, 1]
# [1, 2, 1]
# [1, 3, 3, 1]
# [1, 4, 6, 4, 1]
# [1, 5, 10, 10, 5, 1]
# [1, 6, 15, 20, 15, 6, 1]
# [1, 7, 21, 35, 35, 21, 7, 1]
# [1, 8, 28, 56, 70, 56, 28, 8, 1]
# [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
n = 0
results = []
for t in triangles():
    results.append(t)
    n = n + 1
    if n == 10:
        break

for t in results:
    print(t)

if results == [
    [1],
    [1, 1],
    [1, 2, 1],
    [1, 3, 3, 1],
    [1, 4, 6, 4, 1],
    [1, 5, 10, 10, 5, 1],
    [1, 6, 15, 20, 15, 6, 1],
    [1, 7, 21, 35, 35, 21, 7, 1],
    [1, 8, 28, 56, 70, 56, 28, 8, 1],
    [1, 9, 36, 84, 126, 126, 84, 36, 9, 1]
]:
    print('测试通过!')
else:
    print('测试失败!')

# 迭代器
# 可以被 next()函数调用并不断返回下一个值的对象称为迭代器：Iterator
from collections.abc import Iterator

print(isinstance((x for x in range(1, 11)), Iterator))
print(isinstance([], Iterator))
# 生成器都是iterator对象，但是 list、tuple、dict、str 等虽然是 Itreable，但不是 Iterator
# 但可以使用Iter()函数，将 Iterable 变为 Iterator
print(isinstance(iter([]), Iterator))
print(isinstance(iter('abc'), Iterator))